<?php

/**
 * todo:是否为app和mod定义app_id和mod_id
 */

/*
 * 系统常量
 * ROOT_PATH       = 代码根路径
 * FRAMEWORK_PATH  = FRAMEWORK 路径
 * MICROTIME       = 当前的时间，含毫秒
 * REQUEST_TIME    = 当前的时间
 *
 * 运行时变量/常量
 * $REQUEST_INFO   = array('domain', 'main_domain', 'sub_domain', 'client_ip', 'server_ip', 'uri', 'url', 'ua', 'referer', 'query_string', 'method_post');
 * DOMAIN          = 完整域名
 * SUB_DOMAIN      = 子域名
 * MAIN_DOMAIN     = 域名
 * IS_POST         = 是否为 POST 请求
 * PROJECT_PATH    = 当前平台路径
 * PROJECT         = 当前平台名
 * APP_PATH        = 当前的应用所在的路径
 * APP             = 当前的应用名
 * CONTROLLER      = 当前运行的控制器,GET请求中的c值
 * ACTION          = 包含 GET 请求中 a 的值，默认为 show
 * DISPATCH_FILE   = 最后 require 执行的文件路径
 *
 *
 */
define('ROOT_PATH',      realpath(dirname( __FILE__) . '/../'));

define('FRAMEWORK_PATH', realpath(ROOT_PATH . '/framework'));
define('LOG_PATH',      realpath(ROOT_PATH . '/logs'));
define('MICROTIME',  microtime(true));
define('REQUEST_TIME', $_SERVER['REQUEST_TIME']);

// 定义ROOT_PATH,FRAMEWORK_PATH，引入框架基本类库common.lib，
define('IN_APF',        true);

// 运行环境，0表示生产机，1表示测试机，可根据IP来判断
define('TEST_ENV', 1);
require FRAMEWORK_PATH . '/library/Common.inc.php';

require_library('framework.exception');
set_exception_handler('exception_handler');
// 加载应用配置
require PROJECT_PATH . '/project_config/'. PROJECT . '.project.config.php';
define('LOCALE', $GLOBALS[PROJECT]['PROJECT_CONFIG']['locale']);

require FRAMEWORK_PATH . '/library/Request.class.php';
Request::init();
define('DOMAIN', Request::$info['domain']);
define('MAIN_DOMAIN', Request::$info['main_domain']);
define('SUB_DOMAIN', Request::$info['sub_domain']);

define('APP', $GLOBALS[PROJECT]['APP_CONFIG'][DOMAIN]['app']);
define('APP_PATH', get_app_path(APP));
define('BROWSER_TYPE', Request::get_browser_type());

require APP_PATH . '/config/'. APP . '.app.config.php';
$SERVICE_CONFIG = $GLOBALS[PROJECT]['APP_CONFIG']['default'];

$request_url = Request::$info['url'];
/* 此服务下所有重写规则 */
if ( ! empty($SERVICE_CONFIG['rewrite']))
{
    $rewrites = $SERVICE_CONFIG['rewrite'];

    /* 如果是多级目录则只取第一级 */
    $request_url  = explode('/', $request_url);
    $request_url  = $request_url[0];

    /* 文件重写 */
    if (!empty($rewrites[$request_url]))
    {
        $request_url = $rewrites[$request_url];
    }
    /* 目录重写 */
    elseif (!empty($rewrites['/' . $request_url .'/']))
    {
        $request_url = $rewrites['/' . $request_url . '/'];
    }
    /* 全匹配的情况 */
    elseif (isset($rewrites['*']) === true)
    {
        $request_url = $rewrites['*'];
    }

    unset($rewrites);
}

$dispatch = APP_PATH . '/' . $request_url;
if (substr($dispatch, -4) != '.php')
{
    APF_log('404_2_2.log', date('[Y-m-d H:i:s]', REQUEST_TIME) . '->' . DOMAIN . Request::$info['uri'] . '<-' . $_SERVER['HTTP_REFERER'] . '->' . Request::$info['ua']);
    header_404(', errcode: INDEX3');
}
elseif (file_exists($dispatch) === false)
{
    APF_Logs('404_3_3.log', date('[Y-m-d H:i:s]', REQUEST_TIME) . '->' . DOMAIN . Request::$info['uri'] . '<-' . $_SERVER['HTTP_REFERER'] . '->' . Request::$info['ua']);
    header_404(', errcode: INDEX4');
}

unset($request_url);

define('DISPATCH_FILE', $dispatch);

if (Request::$info['isPost'] === false)
{
    $_POST = array();
}

$__GET    = $_GET;
$__POST   = $_POST;
$__COOKIE = $_COOKIE;

$_GET = $_POST = $_COOKIE = array();
// 严格禁止使用 _REQUEST 数组
$_REQUEST = array();

// todo:对上传文件的类型正确判断

if ($GLOBALS[PROJECT]['PROJECT_CONFIG']['session'] != '')
{
    // 接管SESSION服务framework.session
    //require_module($GLOBALS['PROJECT_CONFIG']['session']);
}

register_shutdown_function('dump_script_exec_profiler');
/* 接管异常处理 */
require_library('framework.exception');
set_exception_handler('exception_handler');

// 保留：加载项目预处理文件prehook.php

// 加载controller.class.php
$baseControllerFile = PROJECT_PATH . '/project_config/controller.class.php';
if (file_exists($baseControllerFile))
{
    require $baseControllerFile;
}
else
{
    die('project base controller is required');
}
require $dispatch;

define('CONTROLLER', APP . '_' . strtr(basename($dispatch), array('.php' => '', '.' => '_')));
define('ACTION', Request::getGet('a', 'trim', 'show'));

if (method_exists(CONTROLLER, 'validate') && call_user_func(array(CONTROLLER, 'validate'), ACTION) === false)
{
    apf_logs('404_4.log', date('[Y-m-d H:i:s]', REQUEST_TIME) . '->' . DOMAIN . $REQUEST_INFO['uri'] . '<-' . $_SERVER['HTTP_REFERER'] . '->' . $REQUEST_INFO['ua']);

    header_404(', errcode: INDEX5');
}

if (Request::$info['isPost'] === true || isset($_SERVER['HTTP_AJAX_REQUEST']) === true)
{
    /* TODO: 之前已经有了，这个还用输出吗？*/
    header('Cache-Control: no-cache');
}

// 在这句之前不应该有输出，所以将不能进入缓冲区，这意味着content-length小于实际值，信息将显示不完整
ob_start('shutdown_to_output');

call_user_func(array(CONTROLLER, 'init'));
call_user_func(array(CONTROLLER, ACTION));

ob_end_flush();
fastcgi_finish_request();

// 程序执行完毕退出
exit(0);

function shutdown_to_output($buffer)
{
    APF_log('dump', $buffer);
    /* 获取当前页面的 Content-type 头 */
    $content_type = '';
    foreach (headers_list() AS $value)
    {
        if ($value{0} !== 'C' && $value{0} !== 'c')
        {
            continue;
        }
        else
        {
            $value = str_ireplace('Content-Type: ', '', $value, $count);
            if ($count > 0)
            {
                $content_type = $value;
                break;
            }
        }
    }

    if ($content_type === '' || $content_type === 'text/html')
    {
        header('Content-Type: text/html; charset=utf-8');

        $buffer = replace_crlf($buffer);
    }
    else
    {
        /* 判断是否可以压缩输出 */
        if ($content_type === 'text/html; charset=utf-8' || stripos($content_type, ' charset=') !== false || stripos($content_type, 'text/') !== false)
        {
            $buffer = replace_crlf($buffer);
        }
    }

    if ($buffer !== '')
    {
        header('Content-Length: ' . strlen($buffer), true);
    }

    return $buffer;
}

/* 将文本中的 \r\n 或者 \r 的方式全部替换成 \n 的方式，并去除不可见字符 */
function replace_crlf($string)
{
    /* 去除不可见字符 */
    $string = str_replace(array("\x0", "\x1", "\x2", "\x3", "\x4", "\x5", "\x6", "\x7", "\x8", "\xb", "\xc", "\xe", "\xf", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f"), '', $string);

    /* 将 TAB 符替换成四个空格 */
    $string = str_replace("\t", "    ", $string);

    $string = str_replace("\r\n", "\n", $string);

    if (strpos($string, "\r") !== false)
    {
        $string = strtr($string, "\r", "\n");
    }

    return trim($string);
}

?>